package com.cet.qz.unit01.chapter1_3;

import java.util.ConcurrentModificationException;
import java.util.Iterator;

/**
 * @program: algorithm
 * @description:
 * @author: 陈恩涛
 * @create: 2021-03-27 21:52
 **/
public class StackImplByLinkTest {

    public static void main(String[] args) {
        Stack<String> strings = new Stack<>();
        strings.push("aa");
        strings.push("bb");
        strings.push("cc");
        strings.push("aa");
        strings.push("bb");
        strings.push("cc");
        String pop1 = strings.pop();
        System.out.println(pop1);
        System.out.println(strings.peek());
        System.out.println("==========");
        for (String string : strings) {
            if ("bb".equals(string)) {
                strings.push("mm");
            }
            System.out.println(string);
        }
        System.out.println("=========");
        System.out.println(strings.size());
    }
}

class Stack<Item> implements Iterable<Item> {

    // 链表节点类
    private class Node {
        private Item item;
        private Node next;
    }

    private Node first; //栈顶指针
    private int N; // 栈中元素个数
    private int modCount; //入栈加出栈次数

    public boolean isEmpty() {
        return N == 0;
    }

    public int size() {
        return N;
    }

    public void push(Item item) {
        Node oldFirst = first;
        first = new Node();
        first.item = item;
        first.next = oldFirst;
        modCount++;
        N++;
    }

    public Item pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈空！");
        }
        Item result = first.item;
        first = first.next;
        modCount++;
        N--;
        return result;
    }

    public Item peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈空！");
        }
        return first.item;
    }

    @Override
    public Iterator<Item> iterator() {
        return new LinkedIterator(first);
    }

    private class LinkedIterator implements Iterator<Item> {

        private Node currentNode;
        private int expectedModCount;

        public LinkedIterator(Node first) {
            this.currentNode = first;
            this.expectedModCount = modCount;
        }

        @Override
        public boolean hasNext() {
            if (expectedModCount != modCount) {
                throw new ConcurrentModificationException();
            }
            return currentNode != null;
        }

        @Override
        public Item next() {
            if (expectedModCount != modCount) {
                throw new ConcurrentModificationException();
            }
            Item result = currentNode.item;
            currentNode = currentNode.next;
            return result;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

}
